﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

using Styx.WoWInternals.DBC;
using Styx.WoWInternals.WoWObjects;
using Styx.WoWInternals;
using Styx.Common;
using Styx.CommonBot.Routines;
using Styx.Helpers;
using Styx.Pathing;
using Styx;
using System.Diagnostics;
using System.Threading;
using System.IO;
using Styx.CommonBot;
using System.Windows.Forms;
using Styx.CommonBot.Inventory;

namespace KingWoW
{
    class EnhancementShamanCombatClass : KingWoWAbstractBaseClass
    {

        private static string Name = "KingWoW EnhancementShaman'";

        #region CONSTANT AND VARIABLES

        //START OF CONSTANTS ==============================
        private const bool LOGGING = true;
        private const bool DEBUG = false;
        private const bool TRACE = false;
        private static KingWoWUtility utils = null;
        private Movement movement = null;
        private ExtraUtils extra = null;
        private ShamanCommon shammyCommon = null;
        private static bool IsCRPaused = false;

        private Random rnd = new Random();
        private int RANDOM_TIME = 0;

        private WoWUnit tank = null;
        private WoWUnit off_tank = null;
        private WoWUnit lastTank = null;
        private WoWUnit lastOffTank = null;
        private bool SoloBotType = false;
        private string BaseBot = "unknown";
        private TalentManager talents = null;
        WoWUnit target = null;
        WoWUnit chainLightningCandidateTarget = null;
        
        private const string DEBUG_LABEL = "DEBUG";
        private const string TRACE_LABEL = "TRACE";
        private const string TANK_CHANGE = "TANK CHANGED";
        private const string OFF_TANK_CHANGE = "OFF TANK CHANGED";
        private const string FACING = "FACING";

        //START OF SPELLS AND AURAS ==============================
        //private const string DRINK = "Drink";
        ///private const string FOOD = "Food";

        
     
        private const string SEARING_TOTEM = "Searing Totem";
        private const string SEARING_FLAMES = "Searing Flames";
        private const string GROUNDING_TOTEM = "Grounding Totem";
        private const string CAPACITOR_TOTEM = "Capacitor Totem";

        private const string PURIFY_SPIRIT = "Purify Spirit";
        private const string WATER_SHIELD = "Water Shield";
        private const string LIGHTNING_SHIELD = "Lightning Shield";
        private const string LIGHTNING_BOLT = "Lightning Bolt";
        private const string MAELSTROM_WEAPON = "Maelstrom Weapon";
        private const string WIND_SHEAR = "Wind Shear";      
        private const string FLAME_SHOCK = "Flame Shock";
        private const string FROST_SHOCK = "Frost Shock";
        private const string LAVA_LASH = "Lava Lash";
        private const string PRIMALSTRIKE = "Primal Strike";        
        private const string STORMSTRIKE = "Stormstrike";
        private const string WINDSTRIKE = "Windstrike";
        private const string UNLEASH_ELEMENTS = "Unleash Elements";
        private const string UNLEASHED_FURY = "Unleashed Fury";
        private const string FIRE_NOVA = "Fire Nova";
        private const string MAGMA_TOTEM = "Magma Totem";
        private const string CHAIN_LIGHTNING = "Chain Lightning";
                                                

        //HEAL
        private const string ANCESTRAL_SPIRIT = "Ancestral Spirit";       
        private const string CLEANSE_SPIRIT = "Cleanse Spirit";
        private const string HEALING_SURGE = "Healing Surge";
        private const string HEALING_RAIN = "Healing Rain";
        private const string HEALING_STREAM_TOTEM = "Healing Stream Totem";
        private const string EARTHBIND_TOTEM = "Earthbind Totem";
        private const string TREMOR_TOTEM = "Tremor Totem";

        private const string GHOST_WOLF = "Ghost Wolf";
        private const string HEX = "hex";
        private const string PURGE = "Purge";

        private const string SPIRIT_WALK = "Spirit Walk";
        private const string TOTEMIC_RECALL = "Totemic Recall";
        
   
        

        //CD
        private const string ASCENDANCE = "Ascendance";
        private const string FERAL_SPIRIT = "Feral Spirit";
        private const string FIRE_ELEMENTAL_TOTEM = "Fire Elemental Totem";
        private const string EARTH_ELEMENTAL_TOTEM = "Earth Elemental Totem";
        
        private const string HEARTH_ELEMENTAL_TOTEM = "Hearth Elemental Totem";
        private const string SHAMANISTIC_RAGE = "Shamanistic Rage";
                  
        //END OF SPELLS AND AURAS ==============================

        //TALENTS
        private const string STONE_BULWALRK_TOTEM = "Stone Bulwark Totem";
        private const string ASTRAL_SHIFT = "Astral Shift";
        private const string EARTHGRAB_TOTEM = "Earthgrab Totem";
        private const string WINDWALK_TOTEM = "Windwalk Totem";
        private const string TOTEMIC_PROJECTION = "Totemic Projection";
        private const string CALL_OF_THE_ELEMENTS = "Call of the Elements";
        private const string ASTRAL_SWIFTNESS = "Ancestral Swiftness";
        private const string ELEMENTAL_MASTERY = "Elemental Mastery";
        private const string ANCESTRAL_GUIDANCE = "Ancestral Guidance";
        //private const string HEALIG_TIDE_TOTEM = "Healing Tide Totem";
        private const string ELEMENTAL_BLAST = "Elemental Blast";
        private const string LIQUID_MAGMA = "Liquid Magma";

        //FIRE ELEMENTAL TOTEM
        private const string EMPOWER = "Empower";
        //EARTH ELEMENTAL TOTEM
        private const string REINFORCE = "Reinforce";
        //END TALENTS
        //END OF CONSTANTS ==============================

        #endregion

        #region Hotkeys
        private static void InitializeHotkey()
        {
            HotkeysManager.Initialize(StyxWoW.Memory.Process.MainWindowHandle);
        }

        private static Hotkey RegisterHotkeyAssignment(string name, Keys key, Action<Hotkey> callback)
        {
            Keys keyCode = key & Keys.KeyCode;
            ModifierKeys mods = ModifierKeys.NoRepeat;

            if ((key & Keys.Shift) != 0)
                mods |= ModifierKeys.Shift;
            if ((key & Keys.Alt) != 0)
                mods |= ModifierKeys.Alt;
            if ((key & Keys.Control) != 0)
                mods |= ModifierKeys.Control;

            return HotkeysManager.Register(name, keyCode, mods, callback);
        }

        private static void RegisterHotkeys()
        {
            RegisterHotkeyAssignment("Routine Pause", (Keys)ExtraUtilsSettings.Instance.PauseKey, hk =>
            {
                try
                {
                    if (!IsCRPaused)
                    {
                        IsCRPaused = true;
                        if (ExtraUtilsSettings.Instance.ViewChatMessages)
                            Lua.DoString(@"print('\124cFFE61515 Paused!')");
                        Logging.Write("KingWoW Routine Paused!");
                    }
                    else
                    {
                        IsCRPaused = false;
                        if (ExtraUtilsSettings.Instance.ViewChatMessages)
                            Lua.DoString(@"print('\124cFF15E61C Resumed!')");
                        Logging.Write("KingWoW Routine Resumed!");
                    }
                }
                catch (Exception e)
                {
                    Logging.Write(e.StackTrace);
                }
            });

            RegisterHotkeyAssignment("AvoidAOE", (Keys)ExtraUtilsSettings.Instance.AvoidAOEKey, hk =>
            {
                EnhancementShamanSettings.Instance.AvoidAOE = !EnhancementShamanSettings.Instance.AvoidAOE;
                if (EnhancementShamanSettings.Instance.AvoidAOE)
                {
                    if (ExtraUtilsSettings.Instance.ViewChatMessages)
                        Lua.DoString(@"print('AvoidAOE \124cFF15E61C Enabled!')");
                    Logging.Write("AvoidAOE Enabled!");
                }

                else
                {
                    if (ExtraUtilsSettings.Instance.ViewChatMessages)
                        Lua.DoString(@"print('AvoidAOE \124cFFE61515 Disabled!')");
                    Logging.Write("AvoidAOE Disabled!");
                }

            });
            RegisterHotkeyAssignment("TotemicProjection", (Keys)ExtraUtilsSettings.Instance.TotemicProjectionHotkey, hk =>
            {
                try
                {
                    Logging.Write("TotemicProjection HOTKEY PRESSED!");
                    TryPutTotemicProjection = true;
                    HotkeyTimer.AutoReset = false;
                    HotkeyTimer.Interval = 2000;
                    HotkeyTimer.Start();
                }
                catch (Exception e)
                {
                    Logging.Write(e.StackTrace);
                }
            });
        }

        private static bool TryPutTotemicProjection = false;
        private static System.Timers.Timer HotkeyTimer = new System.Timers.Timer();

        private bool HotkeyHandle()
        {
            if (TryPutTotemicProjection && utils.CanCast(TOTEMIC_PROJECTION))
            {
                utils.LogActivity("TotemicProjection On Mouse position");
                utils.Cast(TOTEMIC_PROJECTION);
                utils.PerformSingleLeftMouseClick();
                return true;
            }
            return false;
        }

        private static void RemoveHotkeys()
        {
            HotkeysManager.Unregister("Routine Pause");
            HotkeysManager.Unregister("AvoidAOE");
            HotkeysManager.Unregister("TotemicProjection");
        }

        private static void ReRegisterHotkeys()
        {
            RemoveHotkeys();
            RegisterHotkeys();
        }
        #endregion

        /*private DateTime nextTime_SearingTotem_Allowed = DateTime.Now;

        public void SetnextTime_SearingTotem_Allowed()
        {
            //2 seconds avoid duuble cast
            nextTime_SearingTotem_Allowed = DateTime.Now + new TimeSpan(0, 0, 0, 0, 2000);
        }*/

        public EnhancementShamanCombatClass()
        {
            utils = new KingWoWUtility();
            movement = new Movement();
            extra = new ExtraUtils();
            shammyCommon = new ShamanCommon();
            tank = null;
            lastTank = null;;
            SoloBotType = false;
            BaseBot = "unknown";
            talents = new TalentManager();
            nextTimeTryReviveAllowed = DateTime.Now;
            HotkeyTimer.Elapsed += HotkeyTimer_Elapsed;
        }

        void HotkeyTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            TryPutTotemicProjection = false;
        }

        public override bool Combat
        {
            get 
            {
                if ((Me.Mounted && !EnhancementShamanSettings.Instance.AutoDismountOnCombat) || !StyxWoW.IsInGame || !StyxWoW.IsInWorld || Me.Silenced
                    || (!ExtraUtilsSettings.Instance.FastRotation && (utils.IsGlobalCooldown() || Me.IsCasting))
                || utils.IsEatingOrDrinking() || IsCRPaused)
                    return false;
                SetTargetToAttack();

                //UPDATE TANK
                tank = utils.SimpleGetTank(40f);
                if (tank == null || !tank.IsValid || !tank.IsAlive) tank = Me;

                if (tank != null && (lastTank == null || lastTank.Guid != tank.Guid))
                {
                    lastTank = tank;
                    utils.LogActivity(TANK_CHANGE, tank.Class.ToString());
                }
                off_tank = utils.SimpleGetOffTank(40f, tank);
                if (off_tank != null && (lastOffTank == null || lastOffTank.Guid != off_tank.Guid))
                {
                    lastOffTank = off_tank;
                    utils.LogActivity(OFF_TANK_CHANGE, off_tank.Class.ToString());
                }
                return CombatRotation();
            }
        }

        private bool Resurrect()
        {
            foreach (WoWPlayer player in utils.GetResurrectTargets(40f))
            {
                if (Blacklist.Contains(player.Guid, BlacklistFlags.All)) continue;
                else
                {
                    if (player.Distance > 40 || !player.InLineOfSpellSight) return false;
                    else if (utils.CanCast(ANCESTRAL_SPIRIT, player) && EnhancementShamanSettings.Instance.UseResurrection && !Me.IsMoving)
                    {
                        utils.LogActivity(ANCESTRAL_SPIRIT, player.Class.ToString());
                        Blacklist.Add(player, BlacklistFlags.All, new TimeSpan(0, 0, 60));
                        return utils.Cast(ANCESTRAL_SPIRIT, player);
                    }

                    return false;
                }
            }

            return false;
        }

        public override bool Pulse
        {
            get 
            {
                if (Me.IsDead) return MyDeath();
                if (Me.Combat || IsCRPaused || (Me.Mounted && !EnhancementShamanSettings.Instance.AutoDismountOnCombat) || !StyxWoW.IsInGame || !StyxWoW.IsInWorld || Me.Silenced
                    || utils.IsGlobalCooldown() || utils.IsEatingOrDrinking())
                    return false;

                //UPDATE TANK
                tank = utils.SimpleGetTank(40f);
                if (tank == null || !tank.IsValid || !tank.IsAlive) tank = Me;

                if (tank != null && (lastTank == null || lastTank.Guid != tank.Guid))
                {
                    lastTank = tank;
                    utils.LogActivity(TANK_CHANGE, tank.Class.ToString());
                }
                off_tank = utils.SimpleGetOffTank(40f, tank);
                if (off_tank != null && (lastOffTank == null || lastOffTank.Guid != off_tank.Guid))
                {
                    lastOffTank = off_tank;
                    utils.LogActivity(OFF_TANK_CHANGE, off_tank.Class.ToString());
                }
                if (EnhancementShamanSettings.Instance.AutoGhostWulf && !utils.isAuraActive(GHOST_WOLF) && Me.IsMoving && !Me.Mounted && !Me.IsFalling && !Me.IsDead && !Me.IsGhost
                    && Me.MovementInfo.TimeMoved >= EnhancementShamanSettings.Instance.MoveTimeForAutoGhostWulf && !IsCRPaused)
                {
                    utils.LogActivity("moving....autoGhostWolf");
                    return utils.Cast(GHOST_WOLF);
                }
                if (HotkeyHandle()) return true;
                if (!Me.Combat)
                {
                    //try full me
                    if (EnhancementShamanSettings.Instance.UseResurrection)
                        Resurrect();
                    if (EnhancementShamanSettings.Instance.FullMeOOC)
                    {
                        if (!Me.IsMoving && !Me.Combat && !Me.Mounted && !utils.IsEatingOrDrinking()
                            && ((Me.ManaPercent >= 70 && Me.HealthPercent < 90) || (utils.PlayerCountBuff(MAELSTROM_WEAPON) > 2 && Me.HealthPercent < 95)))
                        {
                            if (utils.CanCast(HEALING_SURGE))
                            {
                                utils.LogActivity(HEALING_SURGE, Me.Class.ToString());
                                return utils.Cast(HEALING_SURGE, Me);
                            }
                        }
                    }
                    if (EnhancementShamanSettings.Instance.Totemic_recall_OOC && !Me.Combat
                        && StyxWoW.Me.Totems.Any(t => t.WoWTotem == WoWTotem.Searing || t.WoWTotem == WoWTotem.Magma) && utils.CanCast(TOTEMIC_RECALL))
                    {
                        utils.LogActivity(TOTEMIC_RECALL);
                        return utils.Cast(TOTEMIC_RECALL);
                    }
                }
                if (!Me.Combat && !IsCRPaused && ((tank != null && tank.Combat) || (off_tank != null && off_tank.Combat)))
                {
                    SetTargetToAttack();
                    return CombatRotation();
                }
                return false;
            }
        }

        private DateTime nextTimeTryReviveAllowed;

        public void SetNextTimeTryRevive()
        {
            //3 seconds avoid duuble cast
            nextTimeTryReviveAllowed = DateTime.Now + new TimeSpan(0, 0, 0, 0, 3000);
        }

        private bool MyDeath()
        {
            if (SoloBotType && Me.IsDead && !Me.IsGhost && nextTimeTryReviveAllowed < DateTime.Now)
            {
                Lua.DoString(string.Format("RunMacroText(\"{0}\")", "/script RepopMe()"));
                SetNextTimeTryRevive();
            }
            return false;
        }

        public override bool Pull
        {
            get
            {
                target = Me.CurrentTarget;
                if (target != null && target.IsDead)
                {
                    Me.ClearTarget();
                    SetTargetToAttack();
                }
                if (target != null && !target.IsFriendly && target.Attackable && !target.IsDead)
                {
                    if (!target.InLineOfSpellSight || target.Distance - target.CombatReach -1 > EnhancementShamanSettings.Instance.PullDistance)
                    {
                        movement.KingHealMove(target,movement.meelerange);
                    }
                    if (!Me.IsMoving && !Me.IsFacing(target))
                    {
                        Me.SetFacing(target);
                    }

                    if (utils.CanCast(UNLEASH_ELEMENTS,target,true) )
                    {                        
                        utils.LogActivity(UNLEASH_ELEMENTS, target.SafeName);
                        return utils.Cast(UNLEASH_ELEMENTS, target);
                    }
                    if (utils.CanCast(FLAME_SHOCK,target,true))
                    {
                        utils.LogActivity(FLAME_SHOCK, target.SafeName);
                        return utils.Cast(FLAME_SHOCK, target);
                    }
                    if (utils.CanCast(LIGHTNING_BOLT, target, true))
                    {
                        utils.LogActivity(LIGHTNING_BOLT, target.SafeName);
                        return utils.Cast(LIGHTNING_BOLT, target);
                    }
                }
                return false;
            }
        }

        public override bool Initialize
        {
            get
            {
                Logging.Write("Ciao " + Me.Class.ToString());
                Logging.Write("Welcome to " + Name + " custom class");
                Logging.Write("Tanks All HonorBuddy Forum developers for code inspiration!");
                Logging.Write("Powered by Attilio76");
                BotEvents.OnBotStartRequested += new BotEvents.OnBotStartStopRequestedDelegate(BotEvents_OnBotStart);
                Lua.Events.AttachEvent("GROUP_ROSTER_UPDATE", UpdateGroupChangeEvent);
                RegisterHotkeys();

                Logging.Write("************ XML CONFIGURATION ************");
                Logging.Write(EnhancementShamanSettings.Instance.GetXML().ToString());
                Logging.Write("*******************************************");
                Logging.Write("*******************************************");
                Logging.Write("*******************************************");
                Logging.Write("************ EXTRA CONFIGURATION ************");
                Logging.Write(ExtraUtilsSettings.Instance.GetXML().ToString());
                Logging.Write("*******************************************");
                return true;
            }
        }

        private void UpdateGroupChangeEvent(object sender, LuaEventArgs args)
        {
            Logging.Write("Update Groups composition");
        }

        private float FireNovaRadius = 10f;

        void BotEvents_OnBotStart(EventArgs args)
        {
            ReRegisterHotkeys();
            talents.Update();
            if (talents.HasGlyph("Fire Nova"))
            {
                Logging.Write("Glyph of Fire Nova Detected: increase Fire Nova to 15");
                FireNovaRadius = 15f;
            }
            else
            {
                Logging.Write("Glyph of Fire Nova NOT Detected: decrease Fire Nova radius to 10");
                FireNovaRadius = 10f;
            }
            BotUpdate();
        }

        public override bool UpdateTalentAndGlyph
        {
            get
            {
                ReRegisterHotkeys();
                talents.Update();
                BotUpdate();
                return true;

            }
        }

        public override bool NeedCombatBuffs { get { return Buff(); } }

        public override bool NeedPreCombatBuffs { get { return Buff(); } }

        public override bool NeedPullBuffs { get { return Buff(); } }

        public override bool NeedRest
        {
            get
            {
                if (Me.IsDead || Me.Mounted || Me.InVehicle || (Me.HealthPercent >= 100 && Me.ManaPercent >= 100)) return false;
                if (utils.IsEatingOrDrinking())
                    return true;
                if (Me.ManaPercent <= EnhancementShamanSettings.Instance.ManaPercent
                    && !Me.Combat && !Me.IsMoving && !utils.IsEatingOrDrinking())
                {
                    WoWItem mydrink = Consumable.GetBestDrink(false);
                    if (mydrink != null)
                    {
                        utils.LogActivity("Drinking");
                        Styx.CommonBot.Rest.DrinkImmediate();
                        return true;
                    }
                    return true;
                }
                if (Me.HealthPercent <= EnhancementShamanSettings.Instance.HealthPercent
                    && !Me.Combat && !Me.IsMoving && !utils.IsEatingOrDrinking())
                {
                    WoWItem myfood = Consumable.GetBestFood(false);
                    if (myfood != null)
                    {
                        utils.LogActivity("Eating");
                        Styx.CommonBot.Rest.DrinkImmediate();
                        return true;
                    }
                    return true;
                }
                return false;
            }
        }

        private bool Buff()
        {
            if (utils.Mounted() || IsCRPaused/*ExtraUtilsSettings.Instance.PauseRotation || */)
                return false;          

            //shield
            if (!utils.isAuraActive(LIGHTNING_SHIELD,Me) && utils.CanCast(LIGHTNING_SHIELD))
            {
                utils.LogActivity(LIGHTNING_SHIELD);
                return utils.Cast(LIGHTNING_SHIELD);
            }
            return false;
        }

        private bool BotUpdate()
        {
            if (BaseBot.Equals(BotManager.Current.Name))
                return false;
            if (utils.IsBotBaseInUse("LazyRaider") || utils.IsBotBaseInUse("Tyrael")
                || utils.IsBotBaseInUse("Raid Bot") || utils.IsBotBaseInUse("Enyo"))
            {
                SoloBotType = false;
                BaseBot = BotManager.Current.Name;
                Logging.Write("Base bot detected: " + BotManager.Current.Name);
                return true;
            }

            Logging.Write("Base bot detected: " + BotManager.Current.Name);
            SoloBotType = true;
            BaseBot = BotManager.Current.Name;
            return true;


        }

        private void SetTargetToAttack()
        {
            if (EnhancementShamanSettings.Instance.TargetTypeSelected == EnhancementShamanSettings.TargetType.AUTO)
            {
                if (ExtraUtilsSettings.Instance.provinGround_Targeting)
                    target = utils.getAnyTargetToAttack(30f);
                else
                    target = utils.getTargetToAttack(30f, tank, false, ExtraUtilsSettings.Instance.UseBossLogic);
                if (target != null)
                    target.Target();
            }
            else
                target = Me.CurrentTarget;
        }

        private bool Interrupt()
        {
            if (EnhancementShamanSettings.Instance.AutoInterrupt)
            {
                WoWUnit InterruptTargetCandidate = Me.FocusedUnit;
                if (InterruptTargetCandidate == null || InterruptTargetCandidate.IsDead || !InterruptTargetCandidate.Attackable || !InterruptTargetCandidate.InLineOfSpellSight
                    || InterruptTargetCandidate.Distance - InterruptTargetCandidate.CombatReach - 1 > 25f)
                {
                    if (Me.CurrentTarget != null && Me.CurrentTarget.Attackable && Me.CurrentTarget.Distance - Me.CurrentTarget.CombatReach - 1 <= 25f && Me.CurrentTarget.InLineOfSpellSight)
                        InterruptTargetCandidate = Me.CurrentTarget;
                    else if (target != null && target.Attackable && target.Distance - target.CombatReach - 1 <= 25f && target.InLineOfSpellSight)
                        InterruptTargetCandidate = target;
                }
                if (InterruptTargetCandidate != null && (InterruptTargetCandidate.IsCasting || InterruptTargetCandidate.IsChanneling)
                    && InterruptTargetCandidate.CanInterruptCurrentSpellCast && utils.CanCast(WIND_SHEAR, InterruptTargetCandidate)
                    && Me.IsFacing(InterruptTargetCandidate)
                    && InterruptTargetCandidate.Distance - InterruptTargetCandidate.CombatReach - 1 <= 25f
                    && InterruptTargetCandidate.InLineOfSpellSight
                    && InterruptTargetCandidate.Attackable)
                {
                    RANDOM_TIME = rnd.Next(EnhancementShamanSettings.Instance.Interrupt_MIN_Time, EnhancementShamanSettings.Instance.Interrupt_MAX_Time);

                    if (InterruptTargetCandidate.CurrentCastStartTime.AddMilliseconds(RANDOM_TIME) <= DateTime.Now)
                    {
                        utils.LogActivity(WIND_SHEAR, InterruptTargetCandidate.SafeName);
                        return utils.Cast(WIND_SHEAR, InterruptTargetCandidate);
                    }
                }
            }
            return false;
        }

        private bool CC()
        {
            WoWUnit focused_unit = Me.FocusedUnit;
            if (EnhancementShamanSettings.Instance.UseHex && focused_unit != null && focused_unit.Attackable && focused_unit.InLineOfSpellSight &&
                focused_unit.Distance <= 30 && !utils.isAuraActive(HEX, focused_unit) && utils.CanCast(HEX) && focused_unit.Guid != target.Guid
                && Me.IsFacing(focused_unit))
            {
                utils.LogActivity(HEX, focused_unit.SafeName);
                return utils.Cast(HEX, focused_unit);
            }
            return false;
        }

        private bool EchoOfTheElementsRotation()
        {

            int enemies_count = utils.AllAttaccableEnemyMobsInRange(12f).Count();
            int LL_Charges = utils.SpellCharges(LAVA_LASH);
            int SS_Charges = utils.SpellCharges(STORMSTRIKE);
            int WS_Charges = utils.SpellCharges(WINDSTRIKE);
            int enemies_count_with_FS = utils.EnemiesInRangeHasMyAura(FLAME_SHOCK, 12f, false, ExtraUtilsSettings.Instance.provinGround_Targeting).Count();
                
            if (EnhancementShamanSettings.Instance.EB_on_five && utils.PlayerCountBuff(MAELSTROM_WEAPON) == 5 && utils.CanCast(ELEMENTAL_BLAST)
                && target.Distance - target.CombatReach - 1 <= 40 && Me.IsFacing(target))
            {
                utils.LogActivity(ELEMENTAL_BLAST, target.SafeName);
                return utils.Cast(ELEMENTAL_BLAST, target);
            }
            if (talents.IsSelected(16) && utils.CanCast(UNLEASH_ELEMENTS))
            {
                utils.LogActivity(UNLEASH_ELEMENTS, target.SafeName);
                return utils.Cast(UNLEASH_ELEMENTS, target);
            }

            if (!EnhancementShamanSettings.Instance.AvoidAOE && utils.CanCast(FIRE_NOVA) && utils.EnemyInRangeWithMobsAroundHasMyAura(FLAME_SHOCK, 60f, FireNovaRadius, EnhancementShamanSettings.Instance.FireNova_number, false, ExtraUtilsSettings.Instance.provinGround_Targeting) != null)
            {
                if (utils.CanCast(UNLEASH_ELEMENTS))
                {
                    utils.LogActivity(UNLEASH_ELEMENTS, target.SafeName);
                    return utils.Cast(UNLEASH_ELEMENTS, target);
                }
                utils.LogActivity(FIRE_NOVA);
                return utils.Cast(FIRE_NOVA);
            }

            if (enemies_count >= 2)
            {
                if (utils.CanCast(FLAME_SHOCK) && target.Distance - target.CombatReach - 1 <= 30 &&
                utils.MyAuraTimeLeft(FLAME_SHOCK, target) <= 9000
                && Me.IsFacing(target))
                {
                    utils.LogActivity(FLAME_SHOCK, target.SafeName);
                    return utils.Cast(FLAME_SHOCK, target);
                }
                if (utils.CanCast(LAVA_LASH) && utils.MyAuraTimeLeft(FLAME_SHOCK, target) > 0 
                    && enemies_count_with_FS < enemies_count
                    && target.IsWithinMeleeRange && Me.IsFacing(target))
                {
                    utils.LogActivity(LAVA_LASH + "For spread FS: charges=" + LL_Charges.ToString() + "enemies_count_with_FS=" + enemies_count_with_FS + "enemies_count in 12 range=" + enemies_count, target.SafeName);
                    return utils.Cast(LAVA_LASH, target);
                }
            }

            if (WS_Charges == 2 && !utils.IsGlobalCooldown() && utils.isAuraActive(ASCENDANCE) && target.Distance - target.CombatReach - 1 <= 30 && utils.CanCast(WINDSTRIKE) && Me.IsFacing(target))
            {
                utils.LogActivity(WINDSTRIKE, target.SafeName);
                return utils.Cast(WINDSTRIKE, target);
            }
            if (SS_Charges == 2 && !utils.IsGlobalCooldown() && target.IsWithinMeleeRange && utils.CanCast(STORMSTRIKE) && Me.IsFacing(target))
            {
                utils.LogActivity(STORMSTRIKE + " charges="+SS_Charges.ToString(), target.SafeName);
                return utils.Cast(STORMSTRIKE, target);
            }

            if (LL_Charges == 2 && utils.CanCast(LAVA_LASH)
            && target.IsWithinMeleeRange && Me.IsFacing(target))
            {
                utils.LogActivity(LAVA_LASH + " charges=" + LL_Charges.ToString(), target.SafeName);
                return utils.Cast(LAVA_LASH, target);
            }
                

            if (!EnhancementShamanSettings.Instance.AvoidAOE && !utils.IsGlobalCooldown() && utils.PlayerCountBuff(MAELSTROM_WEAPON) == 5)
            {
                if (target != null && Me.IsFacing(target) && utils.AllAttaccableEnemyMobsInRangeFromTarget(target, 15f, ExtraUtilsSettings.Instance.provinGround_Targeting).Count() >= EnhancementShamanSettings.Instance.ChainLightining_number)
                    chainLightningCandidateTarget = target;
                else if (EnhancementShamanSettings.Instance.autoselectTargetChaining)
                    chainLightningCandidateTarget = utils.EnemyInRangeWithMobsAround(30f, 15f, EnhancementShamanSettings.Instance.ChainLightining_number, true, ExtraUtilsSettings.Instance.provinGround_Targeting);
                else
                    chainLightningCandidateTarget = null;

                if (chainLightningCandidateTarget != null)
                {
                    utils.LogActivity("Instant: " + CHAIN_LIGHTNING, target.SafeName);
                    return utils.Cast(CHAIN_LIGHTNING, target);
                }
            }

            if (!utils.IsGlobalCooldown() && utils.PlayerCountBuff(MAELSTROM_WEAPON) == 5 /*&& (!talents.IsSelected(16) || (talents.IsSelected(16) && Me.HasAura(UNLEASHED_FURY)))*/
                && target.Distance - target.CombatReach - 1 <= 30 && Me.IsFacing(target))
            {
                utils.LogActivity("Instant: " + LIGHTNING_BOLT, target.SafeName);
                return utils.Cast(LIGHTNING_BOLT, target);
            }

            if (!utils.IsGlobalCooldown() && utils.CanCast(UNLEASH_ELEMENTS))
            {
                utils.LogActivity(UNLEASH_ELEMENTS, target.SafeName);
                return utils.Cast(UNLEASH_ELEMENTS, target);
            }

            if (utils.CanCast(FLAME_SHOCK) && target.Distance - target.CombatReach - 1 <= 30 &&
                utils.MyAuraTimeLeft(FLAME_SHOCK, target) <= 9000
                && Me.IsFacing(target))
            {
                utils.LogActivity(FLAME_SHOCK, target.SafeName);
                return utils.Cast(FLAME_SHOCK, target);
            }
     
            if (!utils.IsGlobalCooldown() && utils.CanCast(FROST_SHOCK) && utils.isAuraActive(FLAME_SHOCK, target)
                && !utils.CanCast(WINDSTRIKE) && !utils.CanCast(STORMSTRIKE) && !utils.CanCast(LAVA_LASH)
                && utils.AllAttaccableEnemyMobsInRangeFromTarget(target, FireNovaRadius, ExtraUtilsSettings.Instance.provinGround_Targeting).Count() < EnhancementShamanSettings.Instance.FireNova_number
                && target.Distance - target.CombatReach - 1 <= 30 && Me.IsFacing(target)
                && utils.MyAuraTimeLeft(FLAME_SHOCK, target) > 9000)
            {
                utils.LogActivity(FROST_SHOCK, target.SafeName);
                return utils.Cast(FROST_SHOCK, target);
            }

            if (utils.CanCast(LAVA_LASH)
            && target.IsWithinMeleeRange && Me.IsFacing(target))
            {
                utils.LogActivity(LAVA_LASH, target.SafeName);
                return utils.Cast(LAVA_LASH, target);
            }

            if (!utils.IsGlobalCooldown() && utils.isAuraActive(ASCENDANCE) && target.Distance - target.CombatReach - 1 <= 30 && utils.CanCast(WINDSTRIKE) && Me.IsFacing(target))
            {
                utils.LogActivity(WINDSTRIKE, target.SafeName);
                return utils.Cast(WINDSTRIKE, target);
            }
            if (!utils.IsGlobalCooldown() && target.IsWithinMeleeRange && utils.CanCast(STORMSTRIKE) && Me.IsFacing(target))
            {
                utils.LogActivity(STORMSTRIKE, target.SafeName);
                return utils.Cast(STORMSTRIKE, target);
            }

            if (!EnhancementShamanSettings.Instance.EB_on_five && utils.CanCast(ELEMENTAL_BLAST) && !utils.IsGlobalCooldown()
                && target.Distance - target.CombatReach - 1 <= 40 && utils.PlayerCountBuff(MAELSTROM_WEAPON) >= 3 && Me.IsFacing(target))
            {
                utils.LogActivity(ELEMENTAL_BLAST, target.SafeName);
                return utils.Cast(ELEMENTAL_BLAST, target);
            }

            //relocate totem
            if (EnhancementShamanSettings.Instance.AutoTotemicProjection && talents.IsSelected(9) && utils.CanCast(TOTEMIC_PROJECTION))
            {
                if (shammyCommon.NeedRelocateOrRecastFireTotemToReachUnit(target))
                {
                    utils.LogActivity(TOTEMIC_PROJECTION);
                    utils.Cast(TOTEMIC_PROJECTION);
                    return SpellManager.ClickRemoteLocation(target.Location);
                }
            }

            if (UseAirTotem()) return true;
            if (UseEarthTotem()) return true;

            if (!utils.IsGlobalCooldown() && !Me.IsMoving && EnhancementShamanSettings.Instance.Use_LB_or_CL_as_filler && target.Distance - target.CombatReach - 1 <= 30 &&
                utils.PlayerCountBuff(MAELSTROM_WEAPON) >= EnhancementShamanSettings.Instance.maelstrom_filler_count && Me.IsFacing(target))
            {
                //Filler
                if (utils.AllAttaccableEnemyMobsInRangeFromTarget(target, 15, ExtraUtilsSettings.Instance.provinGround_Targeting).Count() >= EnhancementShamanSettings.Instance.ChainLightining_number)
                {
                    utils.LogActivity("Filler: (malestorn " + utils.PlayerCountBuff(MAELSTROM_WEAPON).ToString() + ")   " + CHAIN_LIGHTNING, target.SafeName);
                    return utils.Cast(CHAIN_LIGHTNING, target);
                }
                else
                {
                    utils.LogActivity("Filler: (malestorn " + utils.PlayerCountBuff(MAELSTROM_WEAPON).ToString() + ")   " + LIGHTNING_BOLT, target.SafeName);
                    return utils.Cast(LIGHTNING_BOLT, target);
                }

            }

            return false;
        }

        private bool CombatRotation()
        {
            extra.UseHealPotion_Healthstone();
            if (HotkeyHandle()) return true;
            if (extra.UseRacials()) return true;
            if (extra.UseTrinket1()) return true;
            if (extra.UseTrinket2()) return true;
            if (extra.UseManaItem()) return true;

            if (UseFireTotem()) return true;
            if (Cleansing()) return true;
            if (Healing()) return true;
            if (UseCD()) return true; 
            if (Interrupt()) return true;
            if (CC()) return true;
            


            if (target != null)
            {
                if ((EnhancementShamanSettings.Instance.AutofaceTarget || SoloBotType) && !Me.IsFacing(target) && !Me.IsMoving)
                {
                    Me.SetFacing(target);
                }

                if (EnhancementShamanSettings.Instance.movementEnabled && (!target.InLineOfSpellSight || !target.IsWithinMeleeRange || ((target.Distance - target.CombatReach - 1) > movement.meelerange)))
                {
                    movement.KingHealMove(target, movement.meelerange);
                }

                if (talents.IsSelected(12))
                {
                    if (EchoOfTheElementsRotation()) return true;
                }
                else
                {
                    int enemies_count = utils.AllAttaccableEnemyMobsInRange(12f).Count();
                    int enemies_count_with_FS = utils.EnemiesInRangeHasMyAura(FLAME_SHOCK, 12f, false, ExtraUtilsSettings.Instance.provinGround_Targeting).Count();

                    if (!utils.IsGlobalCooldown() && EnhancementShamanSettings.Instance.EB_on_five && utils.PlayerCountBuff(MAELSTROM_WEAPON) == 5 && utils.CanCast(ELEMENTAL_BLAST)
                        && target.Distance - target.CombatReach - 1 <= 40 && Me.IsFacing(target))
                    {
                        utils.LogActivity(ELEMENTAL_BLAST, target.SafeName);
                        return utils.Cast(ELEMENTAL_BLAST, target);
                    }
                    if (!utils.IsGlobalCooldown() && talents.IsSelected(16) && utils.CanCast(UNLEASH_ELEMENTS))
                    {
                        utils.LogActivity(UNLEASH_ELEMENTS, target.SafeName);
                        return utils.Cast(UNLEASH_ELEMENTS, target);
                    }

                    if (!EnhancementShamanSettings.Instance.AvoidAOE && utils.CanCast(FIRE_NOVA) && utils.EnemyInRangeWithMobsAroundHasMyAura(FLAME_SHOCK, 60f, FireNovaRadius, EnhancementShamanSettings.Instance.FireNova_number, false, ExtraUtilsSettings.Instance.provinGround_Targeting) != null)
                    {
                        if (utils.CanCast(UNLEASH_ELEMENTS))
                        {
                            utils.LogActivity(UNLEASH_ELEMENTS, target.SafeName);
                            return utils.Cast(UNLEASH_ELEMENTS, target);
                        }
                        utils.LogActivity(FIRE_NOVA);
                        return utils.Cast(FIRE_NOVA);
                    }

                    if (enemies_count >= 2)
                    {
                        if (utils.CanCast(FLAME_SHOCK) && target.Distance - target.CombatReach - 1 <= 30 &&
                        utils.MyAuraTimeLeft(FLAME_SHOCK, target) <= 9000
                        && Me.IsFacing(target))
                        {
                            utils.LogActivity(FLAME_SHOCK, target.SafeName);
                            return utils.Cast(FLAME_SHOCK, target);
                        }
                        if (utils.CanCast(LAVA_LASH) && utils.MyAuraTimeLeft(FLAME_SHOCK, target) > 0
                            && enemies_count_with_FS < enemies_count
                            && target.IsWithinMeleeRange && Me.IsFacing(target))
                        {
                            utils.LogActivity(LAVA_LASH, target.SafeName);
                            return utils.Cast(LAVA_LASH, target);
                        }
                    }



                    if (!EnhancementShamanSettings.Instance.AvoidAOE && !utils.IsGlobalCooldown() && utils.PlayerCountBuff(MAELSTROM_WEAPON) == 5)
                    {
                        if (target != null && Me.IsFacing(target) && utils.AllAttaccableEnemyMobsInRangeFromTarget(target, 15f, ExtraUtilsSettings.Instance.provinGround_Targeting).Count() >= EnhancementShamanSettings.Instance.ChainLightining_number)
                            chainLightningCandidateTarget = target;
                        else if (EnhancementShamanSettings.Instance.autoselectTargetChaining)
                            chainLightningCandidateTarget = utils.EnemyInRangeWithMobsAround(30f, 15f, EnhancementShamanSettings.Instance.ChainLightining_number, true, ExtraUtilsSettings.Instance.provinGround_Targeting);
                        else
                            chainLightningCandidateTarget = null;

                        if (chainLightningCandidateTarget != null)
                        {
                            utils.LogActivity("Instant: " + CHAIN_LIGHTNING, target.SafeName);
                            return utils.Cast(CHAIN_LIGHTNING, target);
                        }
                    }

                    if (!utils.IsGlobalCooldown() && utils.PlayerCountBuff(MAELSTROM_WEAPON) == 5 /*&& (!talents.IsSelected(16) || (talents.IsSelected(16) && Me.HasAura(UNLEASHED_FURY)))*/
                        && target.Distance - target.CombatReach - 1 <= 30 && Me.IsFacing(target))
                    {
                        utils.LogActivity("Instant: " + LIGHTNING_BOLT, target.SafeName);
                        return utils.Cast(LIGHTNING_BOLT, target);
                    }

                    if (!utils.IsGlobalCooldown() && utils.isAuraActive(ASCENDANCE) && target.Distance - target.CombatReach - 1 <= 30 && utils.CanCast(WINDSTRIKE) && Me.IsFacing(target))
                    {
                        utils.LogActivity(WINDSTRIKE, target.SafeName);
                        return utils.Cast(WINDSTRIKE, target);
                    }
                    if (!utils.IsGlobalCooldown() && target.IsWithinMeleeRange && utils.CanCast(STORMSTRIKE) && Me.IsFacing(target))
                    {
                        utils.LogActivity(STORMSTRIKE, target.SafeName);
                        return utils.Cast(STORMSTRIKE, target);
                    }

                    if (utils.CanCast(LAVA_LASH)
                    && target.IsWithinMeleeRange && Me.IsFacing(target))
                    {
                        utils.LogActivity(LAVA_LASH, target.SafeName);
                        return utils.Cast(LAVA_LASH, target);
                    }

                    if (!utils.IsGlobalCooldown() && utils.CanCast(UNLEASH_ELEMENTS))
                    {
                        utils.LogActivity(UNLEASH_ELEMENTS, target.SafeName);
                        return utils.Cast(UNLEASH_ELEMENTS, target);
                    }

                    if (utils.CanCast(FLAME_SHOCK) && target.Distance - target.CombatReach - 1 <= 30 &&
                        utils.MyAuraTimeLeft(FLAME_SHOCK, target) <= 9000
                        && Me.IsFacing(target))
                    {
                        utils.LogActivity(FLAME_SHOCK, target.SafeName);
                        return utils.Cast(FLAME_SHOCK, target);
                    }

                    if (!utils.IsGlobalCooldown() && utils.CanCast(FROST_SHOCK) && utils.isAuraActive(FLAME_SHOCK, target)
                        && !utils.CanCast(WINDSTRIKE) && !utils.CanCast(STORMSTRIKE) && !utils.CanCast(LAVA_LASH)
                        && utils.AllAttaccableEnemyMobsInRangeFromTarget(target, FireNovaRadius, ExtraUtilsSettings.Instance.provinGround_Targeting).Count() < EnhancementShamanSettings.Instance.FireNova_number
                        && target.Distance - target.CombatReach - 1 <= 30 && Me.IsFacing(target)
                        && utils.MyAuraTimeLeft(FLAME_SHOCK, target) > 9000)
                    {
                        utils.LogActivity(FROST_SHOCK, target.SafeName);
                        return utils.Cast(FROST_SHOCK, target);
                    }


                    if (!EnhancementShamanSettings.Instance.EB_on_five && utils.CanCast(ELEMENTAL_BLAST) && !utils.IsGlobalCooldown()
                        && target.Distance - target.CombatReach - 1 <= 40 && utils.PlayerCountBuff(MAELSTROM_WEAPON) >= 3 && Me.IsFacing(target))
                    {
                        utils.LogActivity(ELEMENTAL_BLAST, target.SafeName);
                        return utils.Cast(ELEMENTAL_BLAST, target);
                    }

                    //relocate totem
                    if (EnhancementShamanSettings.Instance.AutoTotemicProjection && talents.IsSelected(9) && utils.CanCast(TOTEMIC_PROJECTION))
                    {
                        if (shammyCommon.NeedRelocateOrRecastFireTotemToReachUnit(target))
                        {
                            utils.LogActivity(TOTEMIC_PROJECTION);
                            utils.Cast(TOTEMIC_PROJECTION);
                            return SpellManager.ClickRemoteLocation(target.Location);
                        }
                    }

                    if (UseAirTotem()) return true;
                    if (UseEarthTotem()) return true;

                    if (!utils.IsGlobalCooldown() && !Me.IsMoving && EnhancementShamanSettings.Instance.Use_LB_or_CL_as_filler && target.Distance - target.CombatReach - 1 <= 30 &&
                        utils.PlayerCountBuff(MAELSTROM_WEAPON) >= EnhancementShamanSettings.Instance.maelstrom_filler_count && Me.IsFacing(target))
                    {
                        //Filler
                        if (utils.AllAttaccableEnemyMobsInRangeFromTarget(target, 15, ExtraUtilsSettings.Instance.provinGround_Targeting).Count() >= EnhancementShamanSettings.Instance.ChainLightining_number)
                        {
                            utils.LogActivity("Filler: (malestorn " + utils.PlayerCountBuff(MAELSTROM_WEAPON).ToString() + ")   " + CHAIN_LIGHTNING, target.SafeName);
                            return utils.Cast(CHAIN_LIGHTNING, target);
                        }
                        else
                        {
                            utils.LogActivity("Filler: (malestorn " + utils.PlayerCountBuff(MAELSTROM_WEAPON).ToString() + ")   " + LIGHTNING_BOLT, target.SafeName);
                            return utils.Cast(LIGHTNING_BOLT, target);
                        }

                    }
                }
            }
            if (EnhancementShamanSettings.Instance.movementEnabled && Me.CurrentTarget != null && !Me.CurrentTarget.IsDead && (!Me.CurrentTarget.InLineOfSpellSight || !Me.CurrentTarget.IsWithinMeleeRange || ((target.Distance - target.CombatReach - 1) > movement.meelerange)))
            {
                movement.KingHealMove(Me.CurrentTarget, movement.meelerange);
            }
            if (EnhancementShamanSettings.Instance.AutoGhostWulf && !utils.isAuraActive(GHOST_WOLF) && Me.IsMoving && !Me.Mounted && !Me.IsFalling && !Me.IsDead && !Me.IsGhost
                    && Me.MovementInfo.TimeMoved >= EnhancementShamanSettings.Instance.MoveTimeForAutoGhostWulf && !IsCRPaused)
            {
                utils.LogActivity("moving....autoGhostWolf");
                return utils.Cast(GHOST_WOLF);
            }
            
            return false;
        }
        


        private bool UseCD()
        {
            /*//Empower
            if (talents.IsSelected(17) && StyxWoW.Me.Totems.Any(t => t.WoWTotem == WoWTotem.FireElemental)
                && utils.CanCastPetAction(EMPOWER) && !utils.isAuraActive(EMPOWER))
            {
                utils.LogActivity(EMPOWER);
                utils.CastPetAction(EMPOWER);
            }

            //Reinforce
            if (talents.IsSelected(17)&& StyxWoW.Me.Totems.Any(t => t.WoWTotem == WoWTotem.EarthElemental)
                && utils.CanCastPetAction(REINFORCE))
            {
                if (!utils.isAuraActive(REINFORCE) && Me.HealthPercent <= 50)
                {
                    utils.LogActivity(REINFORCE);
                    utils.CastPetAction(REINFORCE);
                }
            }*/
            if (Me.Combat && Me.GotTarget)
            {
                if (utils.CanCast(ELEMENTAL_MASTERY)
                    && EnhancementShamanSettings.Instance.ElementalMasteryCD == EnhancementShamanSettings.CDUseType.COOLDOWN)
                {
                    utils.LogActivity(ELEMENTAL_MASTERY);
                    return utils.Cast(ELEMENTAL_MASTERY);
                }
                else if (utils.CanCast(FERAL_SPIRIT) 
                    && EnhancementShamanSettings.Instance.FeralSpiritCD == EnhancementShamanSettings.CDUseType.COOLDOWN)
                {
                    utils.LogActivity(FERAL_SPIRIT);
                    return utils.Cast(FERAL_SPIRIT);
                }
                else if (!utils.isAuraActive(ASCENDANCE) && utils.CanCast(ASCENDANCE) 
                    && EnhancementShamanSettings.Instance.AscendanceCD == EnhancementShamanSettings.CDUseType.COOLDOWN)
                {
                    utils.LogActivity(ASCENDANCE);
                    return utils.Cast(ASCENDANCE);
                }
                else if (utils.CanCast(FIRE_ELEMENTAL_TOTEM) 
                    && EnhancementShamanSettings.Instance.FireElementalCD == EnhancementShamanSettings.CDUseType.COOLDOWN
                    && (!talents.IsSelected(21) || utils.GetSpellCooldown(LIQUID_MAGMA).TotalMilliseconds <= 30000))
                {
                    utils.LogActivity(FIRE_ELEMENTAL_TOTEM);
                    return utils.Cast(FIRE_ELEMENTAL_TOTEM);
                }
                else if (utils.CanCast(EARTH_ELEMENTAL_TOTEM)
                    && EnhancementShamanSettings.Instance.EarthElementalCD == EnhancementShamanSettings.CDUseType.COOLDOWN)
                {
                    utils.LogActivity(EARTH_ELEMENTAL_TOTEM);
                    return utils.Cast(EARTH_ELEMENTAL_TOTEM);
                }

                else if (extra.IsTargetBoss())
                {
                    if (utils.CanCast(ELEMENTAL_MASTERY)
                    && EnhancementShamanSettings.Instance.ElementalMasteryCD == EnhancementShamanSettings.CDUseType.BOSS)
                    {
                        utils.LogActivity(ELEMENTAL_MASTERY);
                        return utils.Cast(ELEMENTAL_MASTERY);
                    }
                    else if (utils.CanCast(FERAL_SPIRIT)
                    && EnhancementShamanSettings.Instance.FeralSpiritCD == EnhancementShamanSettings.CDUseType.BOSS)
                    {
                        utils.LogActivity(FERAL_SPIRIT);
                        return utils.Cast(FERAL_SPIRIT);
                    }
                    else if (!utils.isAuraActive(ASCENDANCE) && utils.CanCast(ASCENDANCE)
                        && EnhancementShamanSettings.Instance.AscendanceCD == EnhancementShamanSettings.CDUseType.BOSS)
                    {
                        utils.LogActivity(ASCENDANCE);
                        return utils.Cast(ASCENDANCE);
                    }
                    else if (utils.CanCast(FIRE_ELEMENTAL_TOTEM) 
                        && EnhancementShamanSettings.Instance.FireElementalCD == EnhancementShamanSettings.CDUseType.BOSS)
                    {
                        utils.LogActivity(FIRE_ELEMENTAL_TOTEM);
                        return utils.Cast(FIRE_ELEMENTAL_TOTEM);
                    }
                    else if (utils.CanCast(EARTH_ELEMENTAL_TOTEM)
                    && EnhancementShamanSettings.Instance.EarthElementalCD == EnhancementShamanSettings.CDUseType.BOSS)
                    {
                        utils.LogActivity(EARTH_ELEMENTAL_TOTEM);
                        return utils.Cast(EARTH_ELEMENTAL_TOTEM);
                    }
                }
            }
            return false;             
        }

        private bool UseFireTotem()
        {
            //if (nextTime_SearingTotem_Allowed < DateTime.Now && target!=null )
            //{
                if (!EnhancementShamanSettings.Instance.AvoidAOE && !Me.IsMoving && utils.AllAttaccableEnemyMobsInRangeFromTarget(Me, 8f, ExtraUtilsSettings.Instance.provinGround_Targeting).Count() >= EnhancementShamanSettings.Instance.MagmaTotem_number
                    && utils.CanCast(MAGMA_TOTEM) /*&& !utils.IsGlobalCooldown() && !Me.IsCasting*/
                    && !StyxWoW.Me.Totems.Any(t => t.WoWTotem == WoWTotem.FireElemental || t.WoWTotem == WoWTotem.Magma))
                {
                    utils.LogActivity(MAGMA_TOTEM);
                    return utils.Cast(MAGMA_TOTEM);
                    //SetnextTime_SearingTotem_Allowed();
                    //return true;
                }
                else if (!Me.IsMoving && utils.AllAttaccableEnemyMobsInRangeFromTarget(Me, 8f, ExtraUtilsSettings.Instance.provinGround_Targeting).Count() < EnhancementShamanSettings.Instance.MagmaTotem_number
                    && utils.CanCast(SEARING_TOTEM) /*&& !utils.IsGlobalCooldown() && !Me.IsCasting*/ 
                    && target.Distance - target.CombatReach - 1 <= 25f 
                    && !StyxWoW.Me.Totems.Any(t => t.WoWTotem == WoWTotem.FireElemental || t.WoWTotem == WoWTotem.Searing))
                {
                    utils.LogActivity(SEARING_TOTEM);
                    return utils.Cast(SEARING_TOTEM);
                    //SetnextTime_SearingTotem_Allowed();
                    //return true;
                }
                
            //}
            if (!EnhancementShamanSettings.Instance.AvoidAOE && StyxWoW.Me.Totems.Any(t => t.WoWTotem == WoWTotem.FireElemental || t.WoWTotem == WoWTotem.Searing || t.WoWTotem == WoWTotem.Magma) && utils.CanCast(LIQUID_MAGMA))
            {
                utils.LogActivity(LIQUID_MAGMA);
                return utils.Cast(LIQUID_MAGMA);
            }
            return false;
        }

        private bool UseAirTotem()
        {
            if (EnhancementShamanSettings.Instance.UseWindWalkTotem && WindwalkTotem()) return true;
            if (EnhancementShamanSettings.Instance.UseCapacitorTotem && CapacitorTotem()) return true;
            if (EnhancementShamanSettings.Instance.UseGroundingTotem && GroundingTotem()) return true;
            return false;
        }

        private bool UseEarthTotem()
        {
            if (EnhancementShamanSettings.Instance.UseTremorTotem && TremorTotem()) return true;
            if (EnhancementShamanSettings.Instance.UseEarthGrabTotem && EarthGrabTotem()) return true;
            if (EnhancementShamanSettings.Instance.UseEarthBindTotem && EarthBindTotem()) return true;
            return false;
        }

        private bool Healing()
        {
            if (Me.HealthPercent <= EnhancementShamanSettings.Instance.ShamanistcRageHP && utils.CanCast(SHAMANISTIC_RAGE))
            {
                utils.LogActivity(SHAMANISTIC_RAGE);
                return utils.Cast(SHAMANISTIC_RAGE, Me);
            }
            if (Me.HealthPercent <= EnhancementShamanSettings.Instance.AS_HP && utils.CanCast(ASTRAL_SHIFT))
            {
                utils.LogActivity(ASTRAL_SHIFT);
                return utils.Cast(ASTRAL_SHIFT, Me);
            }
            if (EnhancementShamanSettings.Instance.AssistHealing)
            {
                if ((utils.AOEHealCount(Me, EnhancementShamanSettings.Instance.HealingTide_AncestralGuidanceHP, 40) >= EnhancementShamanSettings.Instance.HealingTide_AncestralGuidanceNumber)
                    || (EnhancementShamanSettings.Instance.HealingTide_AncestralGuidanceNumber==1 && Me.HealthPercent<=EnhancementShamanSettings.Instance.HealingTide_AncestralGuidanceHP))
                {
                    if (utils.CanCast(ANCESTRAL_GUIDANCE))
                    {
                        utils.LogActivity(ANCESTRAL_GUIDANCE);
                        return utils.Cast(ANCESTRAL_GUIDANCE);
                    }
                }
                if (EnhancementShamanSettings.Instance.HealingSurgeOnlyOnMe && utils.PlayerCountBuff(MAELSTROM_WEAPON) == 5 &&
                    utils.CanCast(HEALING_SURGE))
                {
                    if (Me.HealthPercent <= EnhancementShamanSettings.Instance.HealingSurgeHP)
                    {
                        utils.LogActivity(HEALING_SURGE, Me.Class.ToString());
                        return utils.Cast(HEALING_SURGE, Me);
                    }
                }
                if (!EnhancementShamanSettings.Instance.HealingSurgeOnlyOnMe && utils.PlayerCountBuff(MAELSTROM_WEAPON) == 5 &&
                    utils.CanCast(HEALING_SURGE))
                {
                    WoWUnit healTarget = utils.GetHealTarget(40f);
                    if (healTarget != null && healTarget.HealthPercent <= EnhancementShamanSettings.Instance.HealingSurgeHP)
                    {
                        utils.LogActivity(HEALING_SURGE,healTarget.Class.ToString());
                        return utils.Cast(HEALING_SURGE,healTarget);
                    }          
                }
                if ( utils.CanCast(HEALING_STREAM_TOTEM) && ((utils.AOEHealCount(Me, EnhancementShamanSettings.Instance.HealingStreamHP, 40) >= EnhancementShamanSettings.Instance.HealingStreamNumber)
                    || (EnhancementShamanSettings.Instance.HealingStreamNumber==1 && Me.HealthPercent<=EnhancementShamanSettings.Instance.HealingStreamHP)))
                {
                    utils.LogActivity(HEALING_STREAM_TOTEM);
                    return utils.Cast(HEALING_STREAM_TOTEM);
                }
                
                HealingRain();
                
                
            }
            return false;
        }

        private bool Cleansing()
        {
            if (EnhancementShamanSettings.Instance.UseDispell)
            {
                WoWUnit player = null;
                if (utils.NeedsDispelShammyNotResto(Me))
                    player = Me;
                else if (tank != null && tank.IsAlive && tank.InLineOfSpellSight && tank.Distance - tank.CombatReach - 1 <= 40f && utils.NeedsDispelShammyNotResto(tank))
                    player = tank;
                else if (off_tank != null && off_tank.IsAlive && off_tank.InLineOfSpellSight && off_tank.Distance - off_tank.CombatReach - 1 <= 40f && utils.NeedsDispelShammyNotResto(off_tank))
                    player = off_tank;
                else
                    player = utils.GetDispellTargetShammyNotResto(40f);
                if (player != null && player.Distance < 40)
                {
                    if (utils.CanCast(CLEANSE_SPIRIT))
                    {
                        utils.LogActivity(CLEANSE_SPIRIT, player.SafeName);
                        return utils.Cast(CLEANSE_SPIRIT, player);
                    }
                }
            }
            return false;
        }
        
        private bool HealingRain()
        {
            if (utils.PlayerCountBuff(MAELSTROM_WEAPON) == 5)
            {
                WoWUnit hr_target = null;

                hr_target = utils.BestHealingRainTargetLocation(EnhancementShamanSettings.Instance.HealingRainHP, EnhancementShamanSettings.Instance.HealingRainNumber, false);

                if (hr_target != null)
                {
                    utils.LogActivity(HEALING_RAIN, hr_target.Class.ToString());
                    utils.Cast(HEALING_RAIN);
                    return SpellManager.ClickRemoteLocation(hr_target.Location);
                }
            }
            return false;
        }

        #region COMMON_TOTEM
        //********************** TOTEM *************************************//

        #region AIR_TOTEM
        //******************************** AIR AIR AIR AIR AIR ******************************************
        private bool CapacitorTotem()
        {
            if (Me.Combat && utils.CanCast(CAPACITOR_TOTEM) && !utils.IsGlobalCooldown() && !Me.IsCasting
                && utils.AllAttaccableEnemyMobsInRange(8f).Count() >= 1
                && !StyxWoW.Me.Totems.Any(t => t.WoWTotem == WoWTotem.Grounding || t.WoWTotem == WoWTotem.Capacitor || t.WoWTotem == WoWTotem.Windwalk))
            {
                utils.LogActivity(CAPACITOR_TOTEM);
                return utils.Cast(CAPACITOR_TOTEM);
            }
            return false;
        }

        private bool GroundingTotem()
        {
            if (Me.Combat && utils.CanCast(GROUNDING_TOTEM) && !utils.IsGlobalCooldown() && !Me.IsCasting
                && !StyxWoW.Me.Totems.Any(t => t.WoWTotem == WoWTotem.Grounding || t.WoWTotem == WoWTotem.Capacitor || t.WoWTotem == WoWTotem.Windwalk))
            {
                utils.LogActivity(GROUNDING_TOTEM);
                return utils.Cast(GROUNDING_TOTEM);
            }
            return false;
        }

        private bool WindwalkTotem()
        {
            if (Me.Combat && utils.CanCast(GROUNDING_TOTEM) && !utils.IsGlobalCooldown() && !Me.IsCasting
                && !StyxWoW.Me.Totems.Any(t => t.WoWTotem == WoWTotem.Grounding || t.WoWTotem == WoWTotem.Capacitor || t.WoWTotem == WoWTotem.Windwalk))
            {
                WoWUnit crowdControlledUnit = utils.GetCrowdControlledFriendlyUnit(40f);
                if (crowdControlledUnit != null)
                {
                    utils.LogActivity(WINDWALK_TOTEM);
                    return utils.Cast(WINDWALK_TOTEM);
                }
            }
            return false;
        }

        //*************************************************************************************//
        #endregion

        #region EARTH
        //******************************** EARTH EARTH EARTH EARTH EARTH ******************************************
        private bool EarthBindTotem()
        {
            if (Me.Combat && utils.CanCast(EARTHBIND_TOTEM) && !utils.IsGlobalCooldown() && !Me.IsCasting
                && !StyxWoW.Me.Totems.Any(t => t.WoWTotem == WoWTotem.Earthbind || t.WoWTotem == WoWTotem.EarthElemental || t.WoWTotem == WoWTotem.Tremor || t.WoWTotem == WoWTotem.Earthgrab)
                && utils.AllAttaccableEnemyMobsInRange(10f).Count() >= 1)
            {
                utils.LogActivity(EARTHBIND_TOTEM);
                return utils.Cast(EARTHBIND_TOTEM);
            }
            return false;
        }

        private bool EarthGrabTotem()
        {
            if (Me.Combat && utils.CanCast(EARTHGRAB_TOTEM) && !utils.IsGlobalCooldown() && !Me.IsCasting
                && !StyxWoW.Me.Totems.Any(t => t.WoWTotem == WoWTotem.Earthbind || t.WoWTotem == WoWTotem.EarthElemental || t.WoWTotem == WoWTotem.Tremor || t.WoWTotem == WoWTotem.Earthgrab)
                && utils.AllAttaccableEnemyMobsInRange(10f).Count() >= 1)
            {
                utils.LogActivity(EARTHGRAB_TOTEM);
                return utils.Cast(EARTHGRAB_TOTEM);
            }
            return false;
        }

        private bool TremorTotem()
        {
            if (Me.Combat && utils.CanCast(TREMOR_TOTEM) && !utils.IsGlobalCooldown() && !Me.IsCasting
                && !StyxWoW.Me.Totems.Any(t => t.WoWTotem == WoWTotem.Earthbind || t.WoWTotem == WoWTotem.EarthElemental || t.WoWTotem == WoWTotem.Tremor || t.WoWTotem == WoWTotem.Earthgrab)
                && utils.AllAttaccableEnemyMobsInRange(20f).Count() >= 1)
            {
                WoWUnit crowdControlledUnit = utils.GetCrowdControlledFriendlyUnit(40f);
                if (crowdControlledUnit != null)
                {
                    utils.LogActivity(TREMOR_TOTEM);
                    return utils.Cast(TREMOR_TOTEM);
                }
            }
            return false;
        }

        //*************************************************************************************************************
        #endregion
        //********************** TOTEM END *************************************//
        #endregion
    }
}

